/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package simri.comunicacao.usb;

import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Calendar;

import simri.negocio.collection.ColLeituraSensorC;
import webservice.LeituraSensor;

/**
 *
 * @author Eduardo
 */

public class ComunicacaoUSB implements Runnable, SerialPortEventListener {

	public String DadosLidos=null;
	public int nodeBytes;
	private int baudrate;
	private int timeout;
	private CommPortIdentifier cp;
	private SerialPort porta;
	private OutputStream saida;
	private InputStream entrada;
	private Thread threadLeitura;
	private boolean IDPortaOK;
	private boolean PortaOK;
	private boolean Leitura;
	private boolean Escrita;
	private String Porta;
	public StringBuffer dadosLidos;
	public String DadosRecebidos=null;
	public String retorna=null;
	
	private long tSleep;

	/*
	 * mÃ©todos para setar e resgatar os valores do processo de leitura da serial
	 */

	public void setDadosRecebidos(StringBuffer dadosLidos){
		retorna = new String(dadosLidos);
	}

	public String getDadosRecebidos(){
		return retorna;
	}

	/*
	 * construtor da classe recebendo os parÃ¢metros do seu hardware serial
	 * (Ã© de suma importÃ¢ncia que esses parÃ¢metros estejam corretos,
	 * caso contrÃ¡rio a leitura/escrita serial nÃ£o terÃ¡ sucesso)
	 */

	public ComunicacaoUSB( String p , int b , int t){
		this.Porta = p;
		this.baudrate = b;
		this.timeout = t;
		dadosLidos = new StringBuffer();
	}
	
	public ComunicacaoUSB( String p , int b , int t, long temp){
		this.Porta = p;
		this.baudrate = b;
		this.timeout = t;
		this.tSleep = temp;
		dadosLidos = new StringBuffer();
	}

	/*
	 * mÃ©todos para habilitar hora a escrita hora a leitura serial,
	 * eles serÃ£o muito utilizados para habilitar um ou outro recurso
	 * jÃ¡ que a interface serial nÃ£o suporta leitura e escrita de forma simultÃ¢nea
	 */

	public void HabilitarEscrita(){
		Escrita = true;
		Leitura = false;
	}

	public void HabilitarLeitura(){
		Escrita = false;
		Leitura = true;
	}

	/*
	 * mÃ©todo que irÃ¡ obter o ID da porta para ser utilizado na identificaÃ§Ã£o da mesma
	 */

	public void ObterIdDaPorta(){
		try {
			cp = CommPortIdentifier.getPortIdentifier(Porta);
			if ( cp == null ) {
				System.out.println("Erro na porta");
				IDPortaOK = false;
				System.exit(1);
			}
			IDPortaOK = true;
		}
		catch (Exception e) {
			System.out.println("Erro obtendo ID da porta: " + e);
			IDPortaOK = false;
			System.exit(1);
		}
	}

	/*
	 * mÃ©todo que irÃ¡ abrir a comunicaÃ§Ã£o com a porta serial
	 * apÃ³s essa porta aberta podemos ou enviar ou ler a serial
	 * Ã© muito importante que os dados de DATABITS, STOPBITS, PARITY e FLOWCONTROL
	 * sejam exatos ao do seu equipamento serial
	 * pois sÃ£o parÃ¢metros que vÃ£o estabelecer a velocidade e modo de leitura
	 * e escrita serial do computador com o seu equipamento
	 */

	public void AbrirPorta(){
		try {
			porta = (SerialPort)cp.open("SerialComLeitura", timeout);
			PortaOK = true;
			//configurar parÃ¢metros
			porta.setSerialPortParams(baudrate,
					SerialPort.DATABITS_8,
					SerialPort.STOPBITS_1,
					SerialPort.PARITY_NONE);
			porta.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
			System.out.println("Porta Aberta Com Sucesso.");
		}
		catch(Exception e){
			PortaOK = false;
			System.out.println("Erro abrindo comunicaÃ§Ã£o: " + e);
			System.exit(1);
		}
	}

	/*
	 * mÃ©todo que irÃ¡ habilitar a leitura da porta serial,
	 * vale lembrar que o â€œpulsoâ€� continuo de recebimento da serial serÃ¡ controlado
	 * pelo mÃ©todo abstrato serialEvent, o mÃ©todo entÃ£o monitora a porta
	 * e obtÃ©m as entradas de dados pelo fluxo
	 */

	public void LerDados(){
		if (Escrita == false){
			try {
				entrada = porta.getInputStream();
			} catch (Exception e) {
				System.out.println("Erro de stream: " + e);
				System.exit(1);
			}
			try {
				porta.addEventListener(this);
			} catch (Exception e) {
				System.out.println("Erro de listener: " + e);
				System.exit(1);
			}
			porta.notifyOnDataAvailable(true);
			/*try {
                threadLeitura = new Thread(this);
                threadLeitura.start();
               run();
            } catch (Exception e) {
                System.out.println("Erro de Thread: " + e);
            }*/
		}
	}

	/*
	 * mÃ©todo que irÃ¡ enviar uma string para a porta serial quando invocado
	 */

	public void EnviarUmaString(String msg){
		if (Escrita==true) {
			try {
				saida = porta.getOutputStream();
				System.out.println("FLUXO OK!");
			}
			catch (Exception e) {
				System.out.println("Erro.STATUS: " + e );
			}
			try {
				System.out.println("Enviando um byte para " + Porta );
				System.out.println("Enviando : " + msg );
				saida.write(msg.getBytes());
				Thread.sleep(100);
				saida.flush();
				System.out.println("Dado Enviado com sucesso");
			}
			catch (Exception e) {
				System.out.println("Houve um erro durante o envio. ");
				System.out.println("STATUS: " + e );
				System.exit(1);
			}
		}
		else {
			System.exit(1);
		}
	}

	public void EnviarUmChar(char car){
		if (Escrita==true) {
			try {
				saida = porta.getOutputStream();
				System.out.println("FLUXO OK!");
			}
			catch (Exception e) {
				System.out.println("Erro.STATUS: " + e );
			}
			try {
				System.out.println("Enviando um byte para " + Porta );
				System.out.println("Enviando : " + car );
				saida.write(car);
				Thread.sleep(100);
				saida.flush();
				System.out.println("Envio realizado com sucesso.");
			}
			catch (Exception e) {
				System.out.println("Houve um erro durante o envio. ");
				System.out.println("STATUS: " + e );
				System.exit(1);
			}
		}
		else {
			System.exit(1);
		}
	}



	/*
	 *  mÃ©todo que serÃ¡ o responsÃ¡vel por manter e controlar a execuÃ§Ã£o da Thread
	 * de leitura da aplicaÃ§Ã£o serial
	 */

	public void run(){
		try {
			Thread.sleep(5);
		} catch (Exception e) {
			System.out.println("Erro de Thread: " + e);
		}
	}

	/*
	 * mÃ©todo abstrato serialEvent() vai gerenciar todos os dados recebidos pela serial
	 */

	public void serialEvent(SerialPortEvent ev){
		int novoDado = 0;
		String temp = "";
		LeituraSensor Aq = new LeituraSensor();
		switch (ev.getEventType()) {
		case SerialPortEvent.BI:
		case SerialPortEvent.OE:
		case SerialPortEvent.FE:
		case SerialPortEvent.PE:
		case SerialPortEvent.CD:
		case SerialPortEvent.CTS:
		case SerialPortEvent.DSR:
		case SerialPortEvent.RI:
		case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
			break;
		case SerialPortEvent.DATA_AVAILABLE:
			//Novo algoritmo de leitura.
			while(novoDado != -1){
				try{
					novoDado = entrada.read();
					if(novoDado == -1){
						break;
					}
					if(')' == (char)novoDado){//if('\n' == (char)novoDado){
						//(',' == (char)novoDado) && ('0' != (char)novoDado)
						//long dataJavaUtil = new java.util.Date().getTime();
						//Calendar data = new Calendar((new java.util.Date()).getTime());
						Calendar data = Calendar.getInstance();
						//dataFormatada = new java.text.DateFormatSymbols().geti
						//System.out.println(dataJavaUtil);
						//System.out.println(data.toLocaleString());
						//System.out.println(data.toString());
						String idSensor = temp.substring(1, temp.indexOf('>'));
						String dado = temp.substring((temp.indexOf('(')+1), temp.length());
						System.out.println(temp);
						//String idSensor = "26";
						//String dado = temp.substring(0, temp.length());
						int idAquisicao = Integer.parseInt(idSensor);
						Aq.setValorLeitura(dado);
						Aq.setDataLeitura(data);
						Aq.setIdSensor(idAquisicao);
						dadosLidos.append("ID Leitura: "+Aq.getIdLeitura()+"  ID Sensor: "+ Aq.getIdSensor()+ "  Valor: " + Aq.getValorLeitura()+"  Data: "+ Aq.getDataLeitura().getTime()+"  "+ "\n");
						temp="";
						try {
							ColLeituraSensorC sAq = new ColLeituraSensorC();
							sAq.cadLeitura(Aq);
							//Thread.sleep(tSleep);
							//bd.execSQL("INSERT INTO aquisicao (idsensor, mensagem, data) VALUES ('"+idAquisicao+"','"+Aq.getValorLeitura().trim()+"','"+data+"')");
						} catch (SQLException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (Exception e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
					else{
						temp = temp + ((Character)(char)novoDado).toString();
						System.out.println(temp);
					}
				}
				catch(IOException ioe){
					System.out.println("Erro de leitura serial: " + ioe);
				}
			}
			setDadosRecebidos(dadosLidos);
			System.out.println(getDadosRecebidos());
			break;
		}
	}

	/*
	 * mÃ©todos para fechar a serial
	 */

	public void FecharCom(){
		try {
			porta.close();
			System.out.println("Porta Fechada com Sucesso.");
		}
		catch (Exception e) {
			System.out.println("Erro fechando porta: " + e);
			System.exit(0);
		}
	}

	public String obterPorta(){
		return Porta;
	}

	public int obterBaudrate(){
		return baudrate;
	}

	public long gettSleep() {
		return tSleep;
	}

	public void settSleep(long tSleep) {
		this.tSleep = tSleep;
	}
}